package com.shop.loan.service.impl;

import cn.hutool.core.date.DateUtil;
import com.github.pagehelper.PageHelper;
import com.shop.loan.mapper.LoanOrderBillByMybatisMapper;
import com.shop.loan.mapper.LoanOrderByMybatisMapper;
import com.shop.loan.mapper.UserBankByMybatisMapper;
import com.shop.loan.model.common.Code;
import com.shop.loan.model.common.ResResult;
import com.shop.loan.model.entity.LoanOrderBillByMybatis;
import com.shop.loan.model.entity.LoanOrderByMybatis;
import com.shop.loan.model.entity.SettingByMybatis;
import com.shop.loan.model.entity.UserBankByMybatis;
import com.shop.loan.model.enums.OrderStatus;
import com.shop.loan.model.enums.PayType;
import com.shop.loan.model.vo.PayVo;
import com.shop.loan.redis.RedisCache;
import com.shop.loan.redis.RedisLockUtil;
import com.shop.loan.redis.RedisUtil;
import com.shop.loan.service.PayService;
import com.shop.loan.service.SettingService;
import com.shop.loan.service.WithHoldService;
import com.shop.loan.util.Util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service
public class WithHoldServiceImpl implements WithHoldService {

    @Resource
    SettingService settingService;

    @Resource
    RedisUtil redisUtil;

    @Resource
    RedisLockUtil redisLockUtil;

    @Resource
    LoanOrderByMybatisMapper loanOrderByMybatisMapper;

    @Resource
    LoanOrderBillByMybatisMapper loanOrderBillByMybatisMapper;

    @Resource
    PayService payService;

    @Resource
    UserBankByMybatisMapper userBankByMybatisMapper;

    @Async
    @Override
    public void withholdByToday() {
        boolean isRun = false;
        SettingByMybatis settingByMybatis = settingService.getSetting();
        if (settingByMybatis.getWithholdExpire() == null || !settingByMybatis.getWithholdExpire()) {
            log.info("【withholdByToday】未开启到期自动代扣");
            return;
        }
        String thisTime = DateUtil.thisHour(true) + ":" + DateUtil.thisMinute();
        String withhold_hour = settingByMybatis.getWithholdHour();
        if (StringUtils.hasLength(withhold_hour)) {
            String[] withhold_hours = withhold_hour.split(",");
            for (String withholdHour : withhold_hours) {
                if (thisTime.trim().equals(withholdHour)) {
                    isRun = true;
                }
            }
        }
        if (!isRun) {
            log.info("【withholdByToday】时辰不对");
            return;
        }
        LoanOrderByMybatis search = new LoanOrderByMybatis();
        if (DateUtil.thisHour(true) == 23) {
            //晚上11点时候 扣除第二天到期的订单
            search.setStartTime(DateUtil.beginOfDay(DateUtil.offsetDay(new Date(), 1)).toString());
            search.setEndTime(DateUtil.endOfDay(DateUtil.offsetDay(new Date(), 1)).toString());
        } else {
            search.setStartTime(DateUtil.beginOfDay(new Date()).toString());
            search.setEndTime(DateUtil.endOfDay(new Date()).toString());
        }
        search.setPayStatus(0);//未还
        search.setStatus(OrderStatus.underway.getStatus());
        PageHelper.startPage(1, 9999);
        List<LoanOrderByMybatis> todayByList = loanOrderByMybatisMapper.selectOrderListByDay(search);
        withhold(todayByList, false);
    }

    @Async
    @Override
    public void withholdByOverdue() {
        boolean isRun = false;
        SettingByMybatis settingByMybatis = settingService.getSetting();
        if (settingByMybatis.getWithholdOverdue() == null || !settingByMybatis.getWithholdOverdue()) {
            log.info("【withholdByOverdue】未开启逾期自动代扣");
            return;
        }
        String thisTime = DateUtil.thisHour(true) + ":" + DateUtil.thisMinute();

        String withhold_hour = settingByMybatis.getWithholdHourByOverdue();
        if (StringUtils.hasLength(withhold_hour)) {
            String[] withhold_hours = withhold_hour.split(",");
            for (String withholdHour : withhold_hours) {
                if (thisTime.trim().equals(withholdHour)) {
                    isRun = true;
                }
            }
        }
        if (!isRun) {
            log.info("【withholdByOverdue】时辰不对");
            return;
        }
        PageHelper.startPage(1, 99999);
        List<LoanOrderByMybatis> overdueByList = loanOrderByMybatisMapper.selectOverdueByList();
        withhold(overdueByList, true);
    }


    /**
     * 代扣操作
     *
     * @param withholdByList
     */
    private void withhold(List<LoanOrderByMybatis> withholdByList, boolean isOverdue) {
        if (withholdByList == null || withholdByList.size() <= 0) {
            log.info(isOverdue + ",订单为空，无需代扣");
            return;
        }
        Jedis jedis = redisUtil.getJedis();
        String lockKey = RedisCache.todayWithholdLock;
        if (isOverdue) {
            lockKey = RedisCache.overdueWithholdLock;
        }
        String lockValue = UUID.randomUUID().toString();
        try {
            if (!redisLockUtil.lock(jedis, lockKey, lockValue)) {
                log.error("【" + lockKey + "】锁被占用");
                return;
            }
            for (LoanOrderByMybatis loanOrderByMybatis : withholdByList) {
                LoanOrderBillByMybatis loanOrderBillByMybatis = loanOrderBillByMybatisMapper.selectFirstUnPay(loanOrderByMybatis.getId());
                if (loanOrderBillByMybatis == null || loanOrderBillByMybatis.getId() == null) {
                    log.error("用户订单账单待支付为空：{}", loanOrderByMybatis.getId());
                    continue;
                }

                UserBankByMybatis userBankByMybatis = userBankByMybatisMapper.selectByPrimaryKey(loanOrderByMybatis.getBankId());
                if (userBankByMybatis == null || userBankByMybatis.getIsDelete()) {
                    log.error("用户订单银行卡为空：{}", loanOrderByMybatis.getUserId());
                    continue;
                }
//                List<UserBankByMybatis> userBankByMybatisList = userBankByMybatisMapper.selectByUser(loanOrderByMybatis.getUserId());
//                if (userBankByMybatisList == null || userBankByMybatisList.size() <= 0) {
//                    log.error("用户绑卡列表为空：{}", loanOrderByMybatis.getUserId());
//                    continue;
//                }

                PayVo payVo = new PayVo();
                payVo.setOpIp(loanOrderByMybatis.getOrderIp());
                payVo.setOrderId(loanOrderByMybatis.getId());
                payVo.setPayType(PayType.principal_interest.getType());
                payVo.setOpId(loanOrderByMybatis.getUserId());
                payVo.setPFrom(loanOrderByMybatis.getPFrom());
                payVo.setBindCardId(userBankByMybatis.getProtocol());
                payVo.setRemark("代扣");
                ResResult payRes = payService.readyPay(payVo, true);
                if (payRes.getCode() == Code.SUCCESS.getCode().intValue() || payRes.getCode() == Code.NOT_NEED_PAY.getCode().intValue()) {
                    //代扣成功 或者 本息无需支付 则代扣担保费
                    log.info("订单【{}】本息代扣成功，订单号为:{}", loanOrderByMybatis.getId(), payRes.getData());
                    if (payRes.getData() != null) {
                        redisUtil.set(RedisCache.withholdSuccessByPi + loanOrderByMybatis.getId() + "_" + loanOrderBillByMybatis.getId(), payRes.getData().toString());
                    }

                    Thread.sleep(100);
                    payVo.setPayType(PayType.goods.getType());
                    payRes = payService.readyPay(payVo, true);
                    if (payRes.getCode() == Code.SUCCESS.getCode().intValue()) {
                        log.info("订单【{}】担保费代扣成功，订单号为:{}", loanOrderByMybatis.getId(), payRes.getData());
                        if (payRes.getData() != null) {
                            redisUtil.set(RedisCache.withholdSuccessByGu + loanOrderByMybatis.getId() + "_" + loanOrderBillByMybatis.getId(), payRes.getData().toString());
                        }
                        Thread.sleep(100);
                    }
                }
                Thread.sleep(100);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(Util.GetErrorDetails(e));
        } finally {
            if (jedis != null) {
                redisLockUtil.release(jedis, lockKey, lockValue);
                jedis.close();
            }
        }
    }

}
